package com.practice.niuke.new_direct_basics.class14;

/**
 * 给定两个有符号32位整数a和b， 返回a和b中较大的。
 * 【要求】
 * 不用做任何比较判断。
 */
public class Code01_GetMax {

	// 请保证输入的参数n，不是0就是1，
    // 函数的功能：1变0,0变1
	// 1 -> 0
	// 0 -> 1
	public static int flip(int n) {
		return n ^ 1;
	}

	// 如果n是非负数，返回1
	// 如果n是负数，返回0
	public static int sign(int n) {
		return flip(
		        // n如果是负数得到1， n是非负数得到0
		        (n >> 31) & 1
        );
	}

	// a, b中较大的返回；
    // 该函数的缺点：当a-b的值如果溢出了，这个函数错。
	public static int getMax1(int a, int b) {
		int c = a - b;
		int scA = sign(c); // a-b为非负，scA为1；a-b为负，scA为0
		int scB = flip(scA); // scA为0，scB为1；scA为1，scB为0
		// scA为0，scb必为1；scA为1，scB必为0
		return a * scA + b * scB;
	}

    /**
     * a, b中较大的返回；
     * a-b的值如果溢出了也正确
     *
     * @param a
     * @param b
     * @return
     */
	public static int getMax2(int a, int b) {
		int c = a - b;
		// a的符号，非负1，负0
		int sa = sign(a);
        // b的符号，非负1，负0
		int sb = sign(b);
        // (a-b)的符号，非负1，负0
		int sc = sign(c);
        // a和b的符号是否一样，不一样为1；一样为0
		int difSab = sa ^ sb;
        // a和b的符号是否一样，a和b的符号一样为1；不一样为0
		int sameSab = flip(difSab);
		int returnA = difSab * sa + sameSab * sc;
		int returnB = flip(returnA);
		return a * returnA + b * returnB;
	}

	public static void main(String[] args) {
		int a = -16;
		int b = 1;
		System.out.println(getMax1(a, b));
		System.out.println(getMax2(a, b));
		a = 2147483647;
		b = -2147480000;
		System.out.println(getMax1(a, b)); // wrong answer because of overflow
		System.out.println(getMax2(a, b));

	}

}
